/**
 * 
 */
package cn.g31010.sip.service.impl;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.adapter.IApplication;
import org.red5.server.api.IClient;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
import org.red5.server.api.Red5;
import org.red5.server.api.scheduling.IScheduledJob;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.red5.server.api.service.IServiceCapableConnection;
import org.red5.server.api.so.ISharedObject;
import org.red5.server.api.so.ISharedObjectSecurity;
import org.red5.server.api.stream.IBroadcastStream;
import org.red5.server.api.stream.IOnDemandStream;
import org.red5.server.api.stream.IPlayItem;
import org.red5.server.api.stream.IPlaylistSubscriberStream;
import org.red5.server.api.stream.IServerStream;
import org.red5.server.api.stream.IStreamAwareScopeHandler;
import org.red5.server.api.stream.IStreamCapableConnection;
import org.red5.server.api.stream.IStreamPlaybackSecurity;
import org.red5.server.api.stream.IStreamPublishSecurity;
import org.red5.server.api.stream.ISubscriberStream;
import org.red5.server.api.stream.support.SimpleConnectionBWConfig;
import org.red5.server.exception.ClientRejectedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author user
 *
 */
public class Application extends ApplicationAdapter implements IPendingServiceCallback, IStreamAwareScopeHandler
{

	protected static Logger log = LoggerFactory.getLogger("cn.g31010.sip.service.impl.Application");
	
	private IScope appScope;
    private IServerStream serverStream;
	public void addListener(IApplication listener) {
		// TODO Auto-generated method stub
		super.addListener(listener);
	}

	public String addScheduledJob(int interval, IScheduledJob job) {
		// TODO Auto-generated method stub
		return super.addScheduledJob(interval, job);
	}

	public String addScheduledJobAfterDelay(int interval, IScheduledJob job,
			int delay) {
		// TODO Auto-generated method stub
		return super.addScheduledJobAfterDelay(interval, job, delay);
	}

	public String addScheduledOnceJob(Date date, IScheduledJob job) {
		// TODO Auto-generated method stub
		return super.addScheduledOnceJob(date, job);
	}

	public String addScheduledOnceJob(long timeDelta, IScheduledJob job) {
		// TODO Auto-generated method stub
		return super.addScheduledOnceJob(timeDelta, job);
	}

	public boolean appConnect(IConnection conn, Object[] params) {
		 measureBandwidth(conn);
		 if(conn instanceof IStreamCapableConnection)
	        {
	            IStreamCapableConnection streamConn = (IStreamCapableConnection)conn;
	            SimpleConnectionBWConfig bwConfig = new SimpleConnectionBWConfig();
	            bwConfig.getChannelBandwidth()[3] = 0x100000L;
	            bwConfig.getChannelInitialBurst()[3] = 0x20000L;
	            streamConn.setBandwidthConfigure(bwConfig);
	        }
		 
		IServiceCapableConnection service = (IServiceCapableConnection)conn;
        log.info("Client connected {} conn {}", new Object[] {
            conn.getClient().getId(), conn
        });
        log.info("Setting stream id: {}", Integer.valueOf(getClients().size()));
        service.invoke("setId", new Object[] {
            conn.getClient().getId()
        }, this);
        return true;
	}

	public void appDisconnect(IConnection conn) {
		if(appScope == conn.getScope() && serverStream != null)
            serverStream.close();
        super.appDisconnect(conn);
	}

	public boolean appJoin(IClient client, IScope app) {
		log.info("Client joined app {}", client.getId());
        IConnection conn = Red5.getConnectionLocal();
        return true;
	}

	public void appLeave(IClient client, IScope app) {
		// TODO Auto-generated method stub
		super.appLeave(client, app);
	}

	public boolean appStart(IScope app) {
		appScope = app;
		 return true;
	}

	public void appStop(IScope app) {
		// TODO Auto-generated method stub
		super.appStop(app);
	}

	public void cancelGhostConnectionsCleanup() {
		// TODO Auto-generated method stub
		super.cancelGhostConnectionsCleanup();
	}

	public boolean clearSharedObjects(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.clearSharedObjects(scope, name);
	}

	public boolean createSharedObject(IScope scope, String name,
			boolean persistent) {
		// TODO Auto-generated method stub
		return super.createSharedObject(scope, name, persistent);
	}

	public void FCPublish(String streamName) {
		// TODO Auto-generated method stub
		super.FCPublish(streamName);
	}

	public void FCUnpublish() {
		// TODO Auto-generated method stub
		super.FCUnpublish();
	}

	public IBroadcastStream getBroadcastStream(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.getBroadcastStream(scope, name);
	}

	public List<String> getBroadcastStreamNames(IScope scope) {
		// TODO Auto-generated method stub
		return super.getBroadcastStreamNames(scope);
	}

	public long getClientTTL() {
		// TODO Auto-generated method stub
		return super.getClientTTL();
	}

	public int getGhostConnsCleanupPeriod() {
		// TODO Auto-generated method stub
		return super.getGhostConnsCleanupPeriod();
	}

	public Set<IApplication> getListeners() {
		// TODO Auto-generated method stub
		return super.getListeners();
	}

	public IOnDemandStream getOnDemandStream(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.getOnDemandStream(scope, name);
	}

	public List<String> getScheduledJobNames() {
		// TODO Auto-generated method stub
		return super.getScheduledJobNames();
	}

	public ISharedObject getSharedObject(IScope scope, String name,
			boolean persistent) {
		// TODO Auto-generated method stub
		return super.getSharedObject(scope, name, persistent);
	}

	public ISharedObject getSharedObject(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.getSharedObject(scope, name);
	}

	public Set<String> getSharedObjectNames(IScope scope) {
		// TODO Auto-generated method stub
		return super.getSharedObjectNames(scope);
	}

	public Set<ISharedObjectSecurity> getSharedObjectSecurity() {
		// TODO Auto-generated method stub
		return super.getSharedObjectSecurity();
	}

	public double getStreamLength(String name) {
		// TODO Auto-generated method stub
		return super.getStreamLength(name);
	}

	public Set<IStreamPlaybackSecurity> getStreamPlaybackSecurity() {
		// TODO Auto-generated method stub
		return super.getStreamPlaybackSecurity();
	}

	public Set<IStreamPublishSecurity> getStreamPublishSecurity() {
		// TODO Auto-generated method stub
		return super.getStreamPublishSecurity();
	}

	public ISubscriberStream getSubscriberStream(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.getSubscriberStream(scope, name);
	}

	public boolean hasBroadcastStream(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.hasBroadcastStream(scope, name);
	}

	public boolean hasOnDemandStream(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.hasOnDemandStream(scope, name);
	}

	public boolean hasSharedObject(IScope scope, String name) {
		// TODO Auto-generated method stub
		return super.hasSharedObject(scope, name);
	}

	protected void killGhostConnections() {
		// TODO Auto-generated method stub
		super.killGhostConnections();
	}

	public void measureBandwidth() {
		// TODO Auto-generated method stub
		super.measureBandwidth();
	}

	public void measureBandwidth(IConnection conn) {
		// TODO Auto-generated method stub
		super.measureBandwidth(conn);
	}

	public void registerSharedObjectSecurity(ISharedObjectSecurity handler) {
		// TODO Auto-generated method stub
		super.registerSharedObjectSecurity(handler);
	}

	public void registerStreamPlaybackSecurity(IStreamPlaybackSecurity handler) {
		// TODO Auto-generated method stub
		super.registerStreamPlaybackSecurity(handler);
	}

	public void registerStreamPublishSecurity(IStreamPublishSecurity handler) {
		// TODO Auto-generated method stub
		super.registerStreamPublishSecurity(handler);
	}

	protected boolean rejectClient() throws ClientRejectedException {
		// TODO Auto-generated method stub
		return super.rejectClient();
	}

	protected boolean rejectClient(Object reason)
			throws ClientRejectedException {
		// TODO Auto-generated method stub
		return super.rejectClient(reason);
	}

	public void removeListener(IApplication listener) {
		// TODO Auto-generated method stub
		super.removeListener(listener);
	}

	public void removeScheduledJob(String name) {
		// TODO Auto-generated method stub
		super.removeScheduledJob(name);
	}

	public boolean roomConnect(IConnection conn, Object[] params) {
		// TODO Auto-generated method stub
		return super.roomConnect(conn, params);
	}

	public void roomDisconnect(IConnection conn) {
		// TODO Auto-generated method stub
		super.roomDisconnect(conn);
	}

	public boolean roomJoin(IClient client, IScope room) {
		// TODO Auto-generated method stub
		return super.roomJoin(client, room);
	}

	public void roomLeave(IClient client, IScope room) {
		// TODO Auto-generated method stub
		super.roomLeave(client, room);
	}

	public boolean roomStart(IScope room) {
		// TODO Auto-generated method stub
		return super.roomStart(room);
	}

	public void roomStop(IScope room) {
		// TODO Auto-generated method stub
		super.roomStop(room);
	}

	public void scheduleGhostConnectionsCleanup() {
		// TODO Auto-generated method stub
		super.scheduleGhostConnectionsCleanup();
	}

	public void setClientTTL(int clientTTL) {
		// TODO Auto-generated method stub
		super.setClientTTL(clientTTL);
	}

	public void setGhostConnsCleanupPeriod(int ghostConnsCleanupPeriod) {
		// TODO Auto-generated method stub
		super.setGhostConnsCleanupPeriod(ghostConnsCleanupPeriod);
	}

	public void streamBroadcastClose(IBroadcastStream stream) {
		// TODO Auto-generated method stub
		super.streamBroadcastClose(stream);
	}

	public void streamBroadcastStart(IBroadcastStream stream) {
		// TODO Auto-generated method stub
		super.streamBroadcastStart(stream);
	}

	public void streamPlaylistItemPlay(IPlaylistSubscriberStream stream,
			IPlayItem item, boolean isLive) {
		// TODO Auto-generated method stub
		super.streamPlaylistItemPlay(stream, item, isLive);
	}

	public void streamPlaylistItemStop(IPlaylistSubscriberStream stream,
			IPlayItem item) {
		// TODO Auto-generated method stub
		super.streamPlaylistItemStop(stream, item);
	}

	public void streamPlaylistVODItemPause(IPlaylistSubscriberStream stream,
			IPlayItem item, int position) {
		// TODO Auto-generated method stub
		super.streamPlaylistVODItemPause(stream, item, position);
	}

	public void streamPlaylistVODItemResume(IPlaylistSubscriberStream stream,
			IPlayItem item, int position) {
		// TODO Auto-generated method stub
		super.streamPlaylistVODItemResume(stream, item, position);
	}

	public void streamPlaylistVODItemSeek(IPlaylistSubscriberStream stream,
			IPlayItem item, int position) {
		// TODO Auto-generated method stub
		super.streamPlaylistVODItemSeek(stream, item, position);
	}

	public void streamPublishStart(IBroadcastStream stream) {
		if(log.isDebugEnabled())
            log.debug("stream broadcast start: {}", stream.getPublishedName());
        IConnection current = Red5.getConnectionLocal();
        Iterator it = scope.getConnections();
        do
        {
            if(!it.hasNext())
                break;
            IConnection conn = (IConnection)it.next();
            if(!conn.equals(current) && (conn instanceof IServiceCapableConnection))
            {
                ((IServiceCapableConnection)conn).invoke("newStream", new Object[] {
                    stream.getPublishedName()
                }, this);
                if(log.isDebugEnabled())
                    log.debug("sending notification to {}", conn);
            }
        } while(true);
	}

	public void streamRecordStart(IBroadcastStream stream) {
		// TODO Auto-generated method stub
		super.streamRecordStart(stream);
	}

	public void streamSubscriberClose(ISubscriberStream stream) {
		// TODO Auto-generated method stub
		super.streamSubscriberClose(stream);
	}

	public void streamSubscriberStart(ISubscriberStream stream) {
		// TODO Auto-generated method stub
		super.streamSubscriberStart(stream);
	}

	public void unregisterSharedObjectSecurity(ISharedObjectSecurity handler) {
		// TODO Auto-generated method stub
		super.unregisterSharedObjectSecurity(handler);
	}

	public void unregisterStreamPlaybackSecurity(IStreamPlaybackSecurity handler) {
		// TODO Auto-generated method stub
		super.unregisterStreamPlaybackSecurity(handler);
	}

	public void unregisterStreamPublishSecurity(IStreamPublishSecurity handler) {
		// TODO Auto-generated method stub
		super.unregisterStreamPublishSecurity(handler);
	}

	public void resultReceived(IPendingServiceCall call) {
		log.info("Received result {} for {}", new Object[] {
	            call.getResult(), call.getServiceMethodName()
	        });
	}
	
	public List getStreams()
    {
        IConnection conn = Red5.getConnectionLocal();
        return getBroadcastStreamNames(conn.getScope());
    }

}
